#!/usr/bin/env python3
"""
ESP32摄像头系统集成模块

集成摄像头驱动、视频流服务器和网络管理功能，提供完整的ESP32摄像头解决方案。
实现需求1.1-1.5, 2.1-2.5, 6.3：完整的ESP32摄像头视频流组件。
"""

import logging
import asyncio
import threading
import time
from typing import Optional, Dict, Any, List, Callable
from dataclasses import dataclass
from enum import Enum
import json

from .esp32_camera_config import CameraModel, FrameSize, PixelFormat, ConfigTemplates
from .esp32_camera_driver import ESP32CameraDriver, CameraState, FrameInfo
from .video_stream_server import (
    VideoStreamManager, StreamConfig, StreamProtocol, StreamQuality,
    HTTPStreamServer, RTSPServer
)
from .network_manager import (
    ConnectionManager, ConnectionConfig, WiFiConfig, NetworkState
)

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class SystemState(Enum):
    """系统状态"""
    UNINITIALIZED = "uninitialized"
    INITIALIZING = "initializing"
    READY = "ready"
    STREAMING = "streaming"
    ERROR = "error"
    MAINTENANCE = "maintenance"


@dataclass
class ESP32CameraSystemConfig:
    """ESP32摄像头系统配置"""
    # 摄像头配置
    camera_model: CameraModel = CameraModel.OV2640
    camera_preset: str = "balanced"  # high_quality, high_speed, balanced, low_power
    
    # 流服务器配置
    enable_http_stream: bool = True
    http_port: int = 8080
    http_path: str = "/stream"
    http_quality: StreamQuality = StreamQuality.MEDIUM
    
    enable_rtsp_stream: bool = True
    rtsp_port: int = 8554
    rtsp_path: str = "/stream"
    rtsp_quality: StreamQuality = StreamQuality.HIGH
    
    # 网络配置
    wifi_configs: List[WiFiConfig] = None
    auto_reconnect: bool = True
    connection_timeout: float = 30.0
    
    # 系统配置
    auto_start_streaming: bool = True
    enable_quality_adaptation: bool = True
    max_clients_per_stream: int = 5
    
    # 监控配置
    enable_performance_monitoring: bool = True
    stats_update_interval: float = 5.0
    health_check_interval: float = 10.0
    
    def __post_init__(self):
        if self.wifi_configs is None:
            self.wifi_configs = []


class ESP32CameraSystem:
    """ESP32摄像头系统"""
    
    def __init__(self, config: ESP32CameraSystemConfig):
        self.config = config
        self.state = SystemState.UNINITIALIZED
        
        # 核心组件
        self.camera_driver: Optional[ESP32CameraDriver] = None
        self.stream_manager: Optional[VideoStreamManager] = None
        self.connection_manager: Optional[ConnectionManager] = None
        
        # 监控线程
        self.monitor_thread: Optional[threading.Thread] = None
        self.running = False
        self._stop_event = threading.Event()
        
        # 统计信息
        self.system_stats = {
            'start_time': None,
            'uptime': 0,
            'total_frames_processed': 0,
            'total_bytes_streamed': 0,
            'active_clients': 0,
            'error_count': 0,
            'last_error': None
        }
        
        # 回调函数
        self.state_callback: Optional[Callable[[SystemState], None]] = None
        self.error_callback: Optional[Callable[[Exception], None]] = None
        self.stats_callback: Optional[Callable[[Dict[str, Any]], None]] = None
    
    def set_state_callback(self, callback: Callable[[SystemState], None]):
        """设置状态回调函数"""
        self.state_callback = callback
    
    def set_error_callback(self, callback: Callable[[Exception], None]):
        """设置错误回调函数"""
        self.error_callback = callback
    
    def set_stats_callback(self, callback: Callable[[Dict[str, Any]], None]):
        """设置统计回调函数"""
        self.stats_callback = callback
    
    def _set_state(self, new_state: SystemState):
        """设置系统状态"""
        if self.state != new_state:
            old_state = self.state
            self.state = new_state
            logger.info(f"系统状态变更: {old_state.value} -> {new_state.value}")
            
            if self.state_callback:
                try:
                    self.state_callback(new_state)
                except Exception as e:
                    logger.error(f"状态回调函数执行失败: {e}")
    
    def _handle_error(self, error: Exception):
        """处理系统错误"""
        self.system_stats['error_count'] += 1
        self.system_stats['last_error'] = str(error)
        logger.error(f"系统错误: {error}")
        
        if self.error_callback:
            try:
                self.error_callback(error)
            except Exception as e:
                logger.error(f"错误回调函数执行失败: {e}")
        
        self._set_state(SystemState.ERROR)
    
    async def initialize(self) -> bool:
        """初始化系统"""
        try:
            self._set_state(SystemState.INITIALIZING)
            logger.info("开始初始化ESP32摄像头系统...")
            
            # 1. 初始化摄像头驱动
            if not await self._initialize_camera():
                raise Exception("摄像头初始化失败")
            
            # 2. 初始化流管理器
            if not await self._initialize_stream_manager():
                raise Exception("流管理器初始化失败")
            
            # 3. 初始化连接管理器
            if not self._initialize_connection_manager():
                raise Exception("连接管理器初始化失败")
            
            # 4. 启动监控
            if self.config.enable_performance_monitoring:
                self._start_monitoring()
            
            # 记录启动时间
            self.system_stats['start_time'] = time.time()
            
            self._set_state(SystemState.READY)
            logger.info("ESP32摄像头系统初始化成功")
            
            # 5. 自动开始流式传输
            if self.config.auto_start_streaming:
                return await self.start_streaming()
            
            return True
            
        except Exception as e:
            self._handle_error(e)
            return False
    
    async def _initialize_camera(self) -> bool:
        """初始化摄像头"""
        try:
            logger.info("初始化摄像头驱动...")
            
            # 创建摄像头配置
            if self.config.camera_preset == "high_quality":
                camera_config = ConfigTemplates.high_quality_config(self.config.camera_model)
            elif self.config.camera_preset == "high_speed":
                camera_config = ConfigTemplates.high_speed_config(self.config.camera_model)
            elif self.config.camera_preset == "low_power":
                camera_config = ConfigTemplates.low_power_config(self.config.camera_model)
            else:  # balanced
                camera_config = ConfigTemplates.balanced_config(self.config.camera_model)
            
            # 创建摄像头驱动
            self.camera_driver = ESP32CameraDriver(camera_config)
            
            # 设置回调函数
            self.camera_driver.set_error_callback(self._on_camera_error)
            self.camera_driver.set_state_callback(self._on_camera_state_changed)
            
            # 初始化摄像头
            if not self.camera_driver.initialize():
                raise Exception("摄像头硬件初始化失败")
            
            logger.info("摄像头驱动初始化成功")
            return True
            
        except Exception as e:
            logger.error(f"摄像头初始化失败: {e}")
            return False
    
    async def _initialize_stream_manager(self) -> bool:
        """初始化流管理器"""
        try:
            logger.info("初始化流管理器...")
            
            self.stream_manager = VideoStreamManager()
            
            # 添加HTTP流服务器
            if self.config.enable_http_stream:
                http_config = StreamConfig(
                    protocol=StreamProtocol.HTTP,
                    port=self.config.http_port,
                    path=self.config.http_path,
                    quality=self.config.http_quality,
                    max_clients=self.config.max_clients_per_stream,
                    adaptive_quality=self.config.enable_quality_adaptation
                )
                
                if not self.stream_manager.add_http_server("main_http", http_config):
                    raise Exception("添加HTTP流服务器失败")
            
            # 添加RTSP流服务器
            if self.config.enable_rtsp_stream:
                rtsp_config = StreamConfig(
                    protocol=StreamProtocol.RTSP,
                    port=self.config.rtsp_port,
                    path=self.config.rtsp_path,
                    quality=self.config.rtsp_quality,
                    max_clients=self.config.max_clients_per_stream,
                    adaptive_quality=self.config.enable_quality_adaptation
                )
                
                if not self.stream_manager.add_rtsp_server("main_rtsp", rtsp_config):
                    raise Exception("添加RTSP流服务器失败")
            
            # 设置摄像头驱动
            if self.camera_driver:
                self.stream_manager.set_camera_driver(self.camera_driver)
            
            logger.info("流管理器初始化成功")
            return True
            
        except Exception as e:
            logger.error(f"流管理器初始化失败: {e}")
            return False
    
    def _initialize_connection_manager(self) -> bool:
        """初始化连接管理器"""
        try:
            logger.info("初始化连接管理器...")
            
            # 创建连接配置
            connection_config = ConnectionConfig(
                wifi_configs=self.config.wifi_configs,
                auto_reconnect=self.config.auto_reconnect,
                connection_timeout=self.config.connection_timeout
            )
            
            self.connection_manager = ConnectionManager(connection_config)
            
            # 设置组件引用
            if self.camera_driver:
                self.connection_manager.set_camera_driver(self.camera_driver)
            if self.stream_manager:
                self.connection_manager.set_stream_manager(self.stream_manager)
            
            # 启动连接管理
            if not self.connection_manager.start():
                raise Exception("连接管理器启动失败")
            
            logger.info("连接管理器初始化成功")
            return True
            
        except Exception as e:
            logger.error(f"连接管理器初始化失败: {e}")
            return False
    
    def _start_monitoring(self):
        """启动系统监控"""
        if self.monitor_thread and self.monitor_thread.is_alive():
            return
        
        self.running = True
        self._stop_event.clear()
        
        self.monitor_thread = threading.Thread(
            target=self._monitoring_loop,
            name="ESP32CameraSystemMonitor",
            daemon=True
        )
        self.monitor_thread.start()
        
        logger.info("系统监控已启动")
    
    def _monitoring_loop(self):
        """监控循环"""
        logger.info("系统监控循环开始")
        
        while self.running and not self._stop_event.is_set():
            try:
                # 更新系统统计信息
                self._update_system_stats()
                
                # 执行健康检查
                self._perform_health_check()
                
                # 调用统计回调
                if self.stats_callback:
                    self.stats_callback(self.get_system_status())
                
                # 等待下次更新
                self._stop_event.wait(self.config.stats_update_interval)
                
            except Exception as e:
                logger.error(f"监控循环错误: {e}")
                self._stop_event.wait(1.0)
        
        logger.info("系统监控循环结束")
    
    def _update_system_stats(self):
        """更新系统统计信息"""
        try:
            current_time = time.time()
            
            # 更新运行时间
            if self.system_stats['start_time']:
                self.system_stats['uptime'] = current_time - self.system_stats['start_time']
            
            # 更新摄像头统计
            if self.camera_driver:
                camera_status = self.camera_driver.get_status()
                self.system_stats['total_frames_processed'] = camera_status['stats']['frames_captured']
            
            # 更新流统计
            if self.stream_manager:
                stream_status = self.stream_manager.get_all_status()
                total_clients = 0
                total_bytes = 0
                
                for server_name, server_status in stream_status.get('servers', {}).items():
                    if server_status:
                        total_clients += server_status.get('clients', 0)
                        total_bytes += server_status.get('stats', {}).get('bytes_streamed', 0)
                
                self.system_stats['active_clients'] = total_clients
                self.system_stats['total_bytes_streamed'] = total_bytes
            
        except Exception as e:
            logger.error(f"更新系统统计失败: {e}")
    
    def _perform_health_check(self):
        """执行健康检查"""
        try:
            # 检查摄像头状态
            if self.camera_driver:
                camera_state = self.camera_driver.state
                if camera_state == CameraState.ERROR:
                    logger.warning("检测到摄像头错误状态")
                    # 可以在这里实现自动恢复逻辑
            
            # 检查网络连接状态
            if self.connection_manager:
                connection_status = self.connection_manager.get_status()
                network_state = connection_status.get('network', {}).get('state')
                if network_state == NetworkState.DISCONNECTED.value:
                    logger.warning("检测到网络断开")
            
            # 检查流服务器状态
            if self.stream_manager:
                stream_status = self.stream_manager.get_all_status()
                if not stream_status.get('manager_running', False):
                    logger.warning("检测到流管理器未运行")
            
        except Exception as e:
            logger.error(f"健康检查失败: {e}")
    
    def _on_camera_error(self, error: Exception):
        """摄像头错误回调"""
        logger.error(f"摄像头错误: {error}")
        self.system_stats['error_count'] += 1
        self.system_stats['last_error'] = f"Camera: {error}"
    
    def _on_camera_state_changed(self, state: CameraState):
        """摄像头状态变更回调"""
        logger.info(f"摄像头状态变更: {state.value}")
        
        # 根据摄像头状态调整系统状态
        if state == CameraState.ERROR and self.state != SystemState.ERROR:
            self._set_state(SystemState.ERROR)
        elif state == CameraState.STREAMING and self.state == SystemState.READY:
            self._set_state(SystemState.STREAMING)
    
    async def start_streaming(self) -> bool:
        """开始流式传输"""
        try:
            if self.state not in [SystemState.READY, SystemState.ERROR]:
                logger.error(f"无法开始流式传输，当前状态: {self.state.value}")
                return False
            
            logger.info("开始流式传输...")
            
            # 启动摄像头捕获
            if self.camera_driver and not self.camera_driver.start_capture():
                raise Exception("启动摄像头捕获失败")
            
            # 启动流服务器
            if self.stream_manager and not await self.stream_manager.start_all_servers():
                raise Exception("启动流服务器失败")
            
            self._set_state(SystemState.STREAMING)
            logger.info("流式传输已开始")
            return True
            
        except Exception as e:
            self._handle_error(e)
            return False
    
    def stop_streaming(self):
        """停止流式传输"""
        try:
            if self.state != SystemState.STREAMING:
                return
            
            logger.info("停止流式传输...")
            
            # 停止摄像头捕获
            if self.camera_driver:
                self.camera_driver.stop_capture()
            
            # 停止流服务器
            if self.stream_manager:
                self.stream_manager.stop_all_servers()
            
            self._set_state(SystemState.READY)
            logger.info("流式传输已停止")
            
        except Exception as e:
            self._handle_error(e)
    
    def restart_streaming(self) -> bool:
        """重启流式传输"""
        logger.info("重启流式传输...")
        
        self.stop_streaming()
        time.sleep(2)  # 等待完全停止
        
        return asyncio.run(self.start_streaming())
    
    def get_system_status(self) -> Dict[str, Any]:
        """获取系统状态"""
        status = {
            'system': {
                'state': self.state.value,
                'uptime': self.system_stats['uptime'],
                'total_frames_processed': self.system_stats['total_frames_processed'],
                'total_bytes_streamed': self.system_stats['total_bytes_streamed'],
                'active_clients': self.system_stats['active_clients'],
                'error_count': self.system_stats['error_count'],
                'last_error': self.system_stats['last_error']
            },
            'camera': self.camera_driver.get_status() if self.camera_driver else None,
            'streams': self.stream_manager.get_all_status() if self.stream_manager else None,
            'network': self.connection_manager.get_status() if self.connection_manager else None
        }
        
        return status
    
    def update_camera_config(self, **kwargs) -> bool:
        """更新摄像头配置"""
        if not self.camera_driver:
            logger.error("摄像头驱动未初始化")
            return False
        
        try:
            current_config = self.camera_driver.get_current_config()
            if not current_config:
                logger.error("无法获取当前摄像头配置")
                return False
            
            # 更新配置参数
            for key, value in kwargs.items():
                if hasattr(current_config, key):
                    setattr(current_config, key, value)
                else:
                    logger.warning(f"未知的配置参数: {key}")
            
            # 应用新配置
            return self.camera_driver.update_config(current_config)
            
        except Exception as e:
            logger.error(f"更新摄像头配置失败: {e}")
            return False
    
    def add_wifi_network(self, ssid: str, password: str, priority: int = 0) -> bool:
        """添加WiFi网络配置"""
        try:
            wifi_config = WiFiConfig(
                ssid=ssid,
                password=password,
                priority=priority,
                auto_connect=True
            )
            
            self.config.wifi_configs.append(wifi_config)
            
            if self.connection_manager:
                self.connection_manager.add_wifi_config(wifi_config)
            
            logger.info(f"添加WiFi网络配置: {ssid}")
            return True
            
        except Exception as e:
            logger.error(f"添加WiFi网络配置失败: {e}")
            return False
    
    def force_reconnect(self):
        """强制重连网络"""
        if self.connection_manager:
            self.connection_manager.force_reconnect()
        else:
            logger.error("连接管理器未初始化")
    
    def shutdown(self):
        """关闭系统"""
        logger.info("关闭ESP32摄像头系统...")
        
        # 停止监控
        self.running = False
        self._stop_event.set()
        
        if self.monitor_thread and self.monitor_thread.is_alive():
            self.monitor_thread.join(timeout=5.0)
        
        # 停止流式传输
        self.stop_streaming()
        
        # 关闭连接管理器
        if self.connection_manager:
            self.connection_manager.stop()
        
        # 清理摄像头资源
        if self.camera_driver:
            self.camera_driver.cleanup()
        
        self._set_state(SystemState.UNINITIALIZED)
        logger.info("ESP32摄像头系统已关闭")
    
    def __enter__(self):
        """上下文管理器入口"""
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self.shutdown()


async def main():
    """测试函数"""
    # 创建系统配置
    config = ESP32CameraSystemConfig(
        camera_model=CameraModel.OV2640,
        camera_preset="balanced",
        enable_http_stream=True,
        http_port=8080,
        enable_rtsp_stream=True,
        rtsp_port=8554,
        wifi_configs=[
            WiFiConfig(ssid="TestNetwork", password="password123", priority=1)
        ],
        auto_start_streaming=True,
        enable_performance_monitoring=True
    )
    
    # 创建并初始化系统
    async with ESP32CameraSystem(config) as camera_system:
        # 设置回调函数
        def on_state_changed(state: SystemState):
            print(f"系统状态: {state.value}")
        
        def on_error(error: Exception):
            print(f"系统错误: {error}")
        
        def on_stats_update(stats: Dict[str, Any]):
            print(f"系统统计: 运行时间={stats['system']['uptime']:.1f}s, "
                  f"处理帧数={stats['system']['total_frames_processed']}, "
                  f"活跃客户端={stats['system']['active_clients']}")
        
        camera_system.set_state_callback(on_state_changed)
        camera_system.set_error_callback(on_error)
        camera_system.set_stats_callback(on_stats_update)
        
        # 初始化系统
        if await camera_system.initialize():
            print("ESP32摄像头系统初始化成功")
            
            # 运行一段时间
            await asyncio.sleep(30)
            
            # 显示最终状态
            final_status = camera_system.get_system_status()
            print(f"最终状态: {json.dumps(final_status, indent=2, ensure_ascii=False)}")
            
        else:
            print("ESP32摄像头系统初始化失败")


if __name__ == "__main__":
    asyncio.run(main())